package com.lsh.storage.consumer;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;

import java.io.IOException;

/**
 * @author ：LiuShihao
 * @date ：Created in 2021/9/2 10:16 上午
 * @desc ：
 * Producer发送 消息 到 Broker  会触发ConfirmCallBack确认模式
 * 如果Broker没有投入到正确的队列里 会触发ReturnCallBack退回模式（如果投到了就不会触发）
 * 以及消息接收会有消息接收确认
 */
//@Component
public class MqConsumer {

    @RabbitHandler
    /**直接模式 使用队列名 监听*/
    @RabbitListener(queues = "direct")
    public void receiveDirectMsg(String msg, Channel channel, Message message) throws IOException {
        try {
            System.out.println("direct : 消费者接收消息 "+msg);
            //basicAck：表示成功确认，使用此回执方法后，消息会被rabbitmq broker 删除。
            //deliveryTag：表示消息投递序号，每次消费消息或者消息重新投递后，deliveryTag都会增加。手动消息确认模式下，我们可以对指定deliveryTag的消息进行ack、nack、reject等操作。
            //boolean multiple：是否批量确认，值为 true 则会一次性 ack所有小于当前消息 deliveryTag 的消息。
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);


        }catch (Exception e){

            if (message.getMessageProperties().getRedelivered()) {

                System.out.println("消息已重复处理失败,拒绝再次接收...");
                //basicReject：拒绝消息，与basicNack区别在于不能进行批量操作，其他用法很相似。
                //deliveryTag：表示消息投递序号。
                //requeue：值为 true 消息将重新入队列。
                /**
                 * basicReject：是接收端告诉服务器这个消息我拒绝接收,不处理,
                 * 可以设置是否放回到队列中还是丢掉，而且只能一次拒绝一个消息,
                 * 官网中有明确说明不能批量拒绝消息，为解决批量拒绝消息才有了basicNack。
                 */
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
            } else {

                System.out.println("消息即将再次返回队列处理...");
                //basicNack ：表示失败确认，一般在消费消息业务异常时用到此方法，可以将消息重新投递入队列。
                //deliveryTag：表示消息投递序号。
                //multiple：是否批量确认。
                //requeue：值为 true 消息将重新入队列。
                /**
                 * basicNack：可以一次拒绝N条消息，
                 * 客户端可以设置basicNack方法的multiple参数为true，
                 * 服务器会拒绝指定了delivery_tag的所有未确认的消息(tag是一个64位的long值，最大值是9223372036854775807)。
                 */
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            }



        }
    }


    @RabbitHandler
    /**分裂模式 使用交换机名 监听*/
    @RabbitListener(queues = "fanout1")
    public void receiveFanout1Msg(String msg) {
        System.out.println("fanout1 : 消费者接收消息 "+msg);
    }
    @RabbitHandler
    /**分裂模式 使用队列名 监听*/
    @RabbitListener(queues = "fanout2")
    public void receiveFanout2Msg(String msg) {
        System.out.println("fanout2 : 消费者接收消息 "+msg);
    }

    @RabbitHandler
    /**分裂模式 使用队列名 监听*/
    @RabbitListener(queues = "topic1")
    public void receiveTopic1Msg(String msg) {
        System.out.println("topic1 : orders.#：消费者接收消息 "+msg);
    }
    @RabbitHandler
    /**分裂模式 使用队列名 监听*/
    @RabbitListener(queues = "topic2")
    public void receiveTopic2Msg(String msg) {
        System.out.println("topic2 : #.log：消费者接收消息 "+msg);
    }
    @RabbitHandler
    /**分裂模式 使用队列名 监听*/
    @RabbitListener(queues = "topic3")
    public void receiveTopic3Msg(String msg) {
        System.out.println("topic3 : user.log：消费者接收消息 "+msg);
    }


}
